package com.bit.cfdi.web.vm.negocio;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.DependsOn;
import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Messagebox;

import com.bit.cfdi.web.constants.CFDIConstants;
import com.bit.cfdi.web.domain.Contacto;
import com.bit.cfdi.web.domain.DatosFiscales;
import com.bit.cfdi.web.domain.Direccion;
import com.bit.cfdi.web.domain.Estado;
import com.bit.cfdi.web.domain.Negocio;
import com.bit.cfdi.web.domain.Pais;
import com.bit.cfdi.web.domain.Telefono;
import com.bit.cfdi.web.services.ContactoService;
import com.bit.cfdi.web.services.EstadoService;
import com.bit.cfdi.web.services.NegocioService;
import com.bit.cfdi.web.services.PaisService;
import com.bit.cfdi.web.session.SessionUtils;

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class ConfigurarDatosFiscalesViewModel {
	
	@WireVariable
	private SessionUtils sessionUtils;
	@WireVariable
	private PaisService paisService;
	@WireVariable
	private EstadoService estadoService;
	@WireVariable
	private NegocioService negocioService;
	@WireVariable
	private ContactoService contactoService;
	
	public static final String REQUIRED_VALUE = "Campo requerido";
	

	private String rfc;
	private String razonSocial;
	private Boolean disableRfcField;
	private Direccion direccion;
	private List<Pais> paises;
	private Pais paisSelected;
	private List<Estado> estados;
	private Estado estadoSelected;
	private List<Telefono> telefonos;
	
	private DatosFiscalesErrorMessages errorMsgs;
	
	@Init
	public void init() {
		disableRfcField = false;
		paises = paisService.getAll();
		estados = new ArrayList<Estado>();
		direccion = new Direccion();
		telefonos = new ArrayList<Telefono>();
		errorMsgs = new DatosFiscalesErrorMessages();
		retrieveInitialInfo();
	}
	
	//Getters - Setters
	public String getRfc() {
		return rfc;
	}
	
	public void setRfc(final String rfc) {
		this.rfc = rfc;
	}
	
	public String getRazonSocial() {
		return razonSocial;
	}
	
	public void setRazonSocial(final String razonSocial) {
		this.razonSocial = razonSocial;
	}
	
	public Boolean getDisableRfcField() {
		return disableRfcField;
	}
	
	public Direccion getDireccion() {
		return direccion;
	}
	
	public List<Pais> getPaises() {
		return paises;
	}
	
	public Pais getPaisSelected() {
		return paisSelected;
	}
	
	public void setPaisSelected(final Pais paisSelected) {
		this.paisSelected = paisSelected;
	}
	
	@DependsOn({"paisSelected"})
	public List<Estado> getEstados() {
		if(paisSelected != null) {
			estados = estadoService.getEstadosByPais(paisSelected.getPais());
		}
		return estados;
	}
	
	public Estado getEstadoSelected() {
		return estadoSelected;
	}
	
	public void setEstadoSelected(final Estado estadoSelected) {
		this.estadoSelected = estadoSelected;
	}
	
	public List<Telefono> getTelefonos() {
		return telefonos;
	}
	
	public DatosFiscalesErrorMessages getErrorMsgs() {
		return errorMsgs;
	}
	
	//Local Commands
	@Command @NotifyChange({"telefonos"})
	public void addPhone() {
		telefonos.add(new Telefono());
	}
	
	@Command @NotifyChange({"telefonos"})
	public void deletePhone(@BindingParam("telIndex") Integer telIndex) {
		if(telefonos.get(telIndex.intValue())!=null) {
			telefonos.remove(telIndex.intValue());
		}
	}
	
	@Command @NotifyChange({"*"})
	public void performSave() {
		if(!validateForm()) {
			return;
		}
		Negocio neg = (Negocio) sessionUtils.getFromSession(
				SessionUtils.NEGOCIO);
		neg.getDatosFiscales().setRfc(rfc);
		neg.getDatosFiscales().setRazon(razonSocial);
		Direccion dfdir = neg.getDatosFiscales().getDireccion();
		dfdir.setCalle(direccion.getCalle());
		dfdir.setNoExterior(direccion.getNoExterior());
		dfdir.setNoInterior(direccion.getNoInterior());
		dfdir.setColonia(direccion.getColonia());
		dfdir.setCodigoPostal(direccion.getCodigoPostal());
		dfdir.setReferencia(direccion.getReferencia());
		dfdir.setPais(direccion.getPais());
		dfdir.setEstado(direccion.getEstado());
		dfdir.setCiudad(direccion.getCiudad());
		dfdir.setMunicipio(direccion.getMunicipio());
		dfdir.setLocalidad(direccion.getLocalidad());
		Contacto lastContacto = neg.getContacto();
		Contacto newContacto = new Contacto();
		for(Telefono currentTel : telefonos) {
			if(currentTel.getNumero()==null) {
				currentTel.setNumero("");
			}
			if(currentTel.getExtension()==null) {
				currentTel.setExtension("");
			}
			if(!currentTel.getNumero().trim().isEmpty() ||
					!currentTel.getExtension().trim().isEmpty()) {
				currentTel.setContacto(newContacto);
				newContacto.getTelefonos().add(currentTel);
			}
		}
		neg.setContacto(newContacto);
		negocioService.save(neg);
		if(lastContacto!=null) {
			contactoService.delete(lastContacto);
		}
		updateMessage();
		retrieveInitialInfo();
		
		//Updating nav negocio
		BindUtils.postGlobalCommand(null, null, "negocioRefreshNegocioInfo", 
				null);
	}
	
	//Global Commands
	@GlobalCommand @NotifyChange({"rfc","disableRfcField"})
	public void ConfigurarDatosFiscalesSetRfc(@BindingParam("rfc") String rfc) {
		this.rfc = rfc;
		disableRfcField = true;
	}
	
	//private methods
	private void retrieveInitialInfo() {
		Negocio neg = (Negocio) sessionUtils.getFromSession(
				SessionUtils.NEGOCIO);
		telefonos = new ArrayList<Telefono>();
		rfc = neg.getDatosFiscales().getRfc();
		if(neg.getNegCer()!=null) {
			disableRfcField = true;
		}
		DatosFiscales df = neg.getDatosFiscales();
		razonSocial = df.getRazon();
		Direccion dfdir = neg.getDatosFiscales().getDireccion();
		direccion.setCalle(dfdir.getCalle());
		direccion.setNoExterior(dfdir.getNoExterior());
		direccion.setNoInterior(dfdir.getNoInterior());
		direccion.setColonia(dfdir.getColonia());
		direccion.setCodigoPostal(dfdir.getCodigoPostal());
		direccion.setReferencia(dfdir.getReferencia());
		direccion.setPais(dfdir.getPais());
		direccion.setEstado(dfdir.getEstado());
		direccion.setCiudad(dfdir.getCiudad());
		direccion.setMunicipio(dfdir.getMunicipio());
		direccion.setLocalidad(dfdir.getLocalidad());
		Set<Telefono> negTels = neg.getContacto() != null ? 
				neg.getContacto().getTelefonos() : new HashSet<Telefono>(0);
		for(Telefono currentParsePhone : negTels) {
			Telefono newPhone = new Telefono();
			newPhone.setTipoTelefono(currentParsePhone.getTipoTelefono());
			newPhone.setNumero(currentParsePhone.getNumero());
			newPhone.setExtension(currentParsePhone.getExtension());
			telefonos.add(newPhone);
		}
	}
	
	private boolean validateForm() {
		errorMsgs.cleanMessages();
		boolean empty_messages = false;
		if(rfc == null || rfc.trim().isEmpty()) {
			errorMsgs.setRfcError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(razonSocial == null || razonSocial.trim().isEmpty()) {
			errorMsgs.setRazonError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(direccion.getCalle() == null || 
				direccion.getCalle().trim().isEmpty()) {
			errorMsgs.setCalleError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(direccion.getCodigoPostal() == null || 
				direccion.getCodigoPostal().trim().isEmpty()) {
			errorMsgs.setCpError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(direccion.getPais() == null || 
				direccion.getPais().trim().isEmpty()) {
			errorMsgs.setPaisError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(direccion.getPais() == null || 
				direccion.getEstado().trim().isEmpty()) {
			errorMsgs.setEstadoError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(direccion.getCiudad() == null || 
				direccion.getCiudad().trim().isEmpty()) {
			errorMsgs.setCiudadError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(direccion.getMunicipio() == null || 
				direccion.getMunicipio().trim().isEmpty()) {
			errorMsgs.setMunicipioError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(direccion.getLocalidad() == null || 
				direccion.getLocalidad().trim().isEmpty()) {
			errorMsgs.setLocalidadError(REQUIRED_VALUE);
			empty_messages = true;
		}
		if(empty_messages) {
			return false;
		}
		if(!rfc.matches(CFDIConstants.RFC_PATTERN)) {
			errorMsgs.setRfcError("RFC inválido");
			return false;
		}
		if(!razonSocial.matches(CFDIConstants.RAZON_REGEX)) {
			errorMsgs.setRazonError("Razón social inválida");
			return false;
		}
		return true;
	}
	
	private void updateMessage() {
		Messagebox.show("Los datos se guardaron correctamente");
	}
}
